
// === uuMix.array ===
// depend: uuMeta
/*
Array.prototype.indexOf(search, fromIndex = 0) - return index or -1
Array.prototype.lastIndexOf(search, fromIndex = last) - return index or -1
Array.prototype.every(callback, thisArg = void 0) - return Boolean
Array.prototype.some(callback, thisArg = void 0) - return Boolean
Array.prototype.forEach(callback, thisArg = void 0)
Array.prototype.map(callback, thisArg = void 0) - return [element, ... ]
Array.prototype.filter(callback, thisArg = void 0) - return [element, ... ]
Array.prototype.reduce(callback, initialValue = void 0) - return mix
Array.prototype.reduceRight(callback, initialValue = void 0) - return mix
 */
(function uuMixArrayScope() {

// Array.prototype.indexOf
function ArrayIndexOf(searchElement, // @param Mix:
                      fromIndex) {   // @param Number(= 0):
                                     // @return Number: found index or -1
  var iz = this.length, i = fromIndex || 0;

  i = (i < 0) ? i + iz : i;
  for (; i < iz; ++i) {
    if (i in this && this[i] === searchElement) {
      return i;
    }
  }
  return -1;
}

// Array.prototype.lastIndexOf
function ArrayLastIndexOf(searchElement, // @param Mix:
                          fromIndex) {   // @param Number(= this.length):
                                         // @return Number: found index or -1
  var iz = this.length, i = fromIndex;

  i = (i < 0) ? i + iz : iz - 1;
  for (; i > -1; --i) {
    if (i in this && this[i] === searchElement) {
      return i;
    }
  }
  return -1;
}

// Array.prototype.every
function ArrayEvery(callback,  // @param Function: evaluator
                    thisArg) { // @param ThisObject(= undefined):
                               // @return Boolean:
  for (var i = 0, iz = this.length; i < iz; ++i) {
    if ((i in this) && !callback.call(thisArg, this[i], i, this)) {
      return false;
    }
  }
  return true;
}

// Array.prototype.some
function ArraySome(callback,  // @param Function: evaluator
                   thisArg) { // @param ThisObject(= undefined):
                              // @return Boolean:
  for (var i = 0, iz = this.length; i < iz; ++i) {
    if ((i in this) && callback.call(thisArg, this[i], i, this)) {
      return true;
    }
  }
  return false;
}

// Array.prototype.forEach
function ArrayForEach(callback,  // @param Function: evaluator
                      thisArg) { // @param ThisObject(= undefined):
  for (var i = 0, iz = this.length; i < iz; ++i) {
    (i in this) && callback.call(thisArg, this[i], i, this);
  }
}

// Array.prototype.map
function ArrayMap(callback,  // @param Function: evaluator
                  thisArg) { // @param ThisObject(= undefined):
                             // @return Array: [element, ... ]
  for (var iz = this.length, rv = Array(iz), i = 0; i < iz; ++i) {
    (i in this) && (rv[i] = callback.call(thisArg, this[i], i, this));
  }
  return rv;
}

// Array.prototype.filter
function ArrayFilter(callback,  // @param Function: evaluator
                     thisArg) { // @param ThisObject(= undefined):
                                // @return Array: [element, ... ]
  for (var rv = [], ri = -1, v, i = 0, iz = this.length; i < iz; ++i) {
    if (i in this) {
      v = this[i];
      callback.call(thisArg, v, i, this) && (rv[++ri] = v);
    }
  }
  return rv;
}

// Array.prototype.reduce
function ArrayReduce(callback,       // @param Function: evaluator
                     initialValue) { // @param Mix(= undefined):
                                     // @return Mix:
  var rv, i = 0, iz = this.length, found = 0;

  if (initialValue !== void 0) {
    rv = initialValue;
    ++found;
  }
  for (; i < iz; ++i) {
    if (i in this) {
      rv = found ? callback(rv, this[i], i, this)
                 : (++found, this[i]);
    }
  }
  if (!found) { throw ""; }
  return rv;
}

// Array.prototype.reduceRight
function ArrayReduceRight(callback,       // @param Function: evaluator
                          initialValue) { // @param Mix(= undefined):
                                          // @return Mix:
  var rv, i = 0, found = 0;

  if (initialValue !== void 0) {
    rv = initialValue;
    ++found;
  }
  for (i = this.length - 1; i >= 0; --i) {
    if (i in this) {
      rv = found ? callback(rv, this[i], i, this)
                 : (++found, this[i]);
    }
  }
  if (!found) { throw ""; }
  return rv;
}

// --- initialize ---

// --- export ---
uuMeta.mix(Array.prototype, {
  indexOf:      ArrayIndexOf,     // ECMAScript-262 5th
  lastIndexOf:  ArrayLastIndexOf, // ECMAScript-262 5th
  every:        ArrayEvery,       // ECMAScript-262 5th
  some:         ArraySome,        // ECMAScript-262 5th
  forEach:      ArrayForEach,     // ECMAScript-262 5th
  map:          ArrayMap,         // ECMAScript-262 5th
  filter:       ArrayFilter,      // ECMAScript-262 5th
  reduce:       ArrayReduce,      // ECMAScript-262 5th
  reduceRight:  ArrayReduceRight  // ECMAScript-262 5th
}, 0, 0);

})(); // uuMix.array scope

